package com.ifonly.utils;

import com.ifonly.common.typeconverter.TypeConvert;
import com.ifonly.common.typeconverter.impl.CollectionConverter;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;

/**
 * @author <a href="mailto:ifonlymaster@163.com">ifonly</a>
 * @version 1.0 2015-12-17 16:09
 * @since JDK 1.6
 */
public class BeanUtils {

    public static void setProperty(Object target, Field field, String[] value) {
        try {
            Class<?> clazz = field.getType();
            boolean isAccessible = field.isAccessible();
            if (!isAccessible) {
                field.setAccessible(true);
            }
            if (clazz.isArray()) {
                field.set(target, TypeConvert.convert(clazz, value));
            } else if (Collection.class.isAssignableFrom(clazz)) {
                Type type = field.getGenericType();
                Class<?> targetComponentType = Object.class;
                if(type != null) {
                    if (type instanceof ParameterizedType) { // 如果是泛型参数的类型
                        ParameterizedType pt = (ParameterizedType) type;
                        targetComponentType = (Class) pt.getActualTypeArguments()[0]; // 得到泛型里的class类型对象。
                    }
                }
                CollectionConverter collectionConverter = new CollectionConverter(clazz, targetComponentType);
                Collection collection = collectionConverter.convert(value);
                field.set(target, collection);
            } else {
                field.set(target, TypeConvert.convert(clazz, value[0]));
            }
            field.setAccessible(isAccessible);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }


    public static PropertyDescriptor[] propertyDescriptors(Class<?> clazz) {
        BeanInfo beanInfo;
        try {
            beanInfo = Introspector.getBeanInfo(clazz);
        } catch (IntrospectionException e) {
            throw new RuntimeException(e);
        }
        return beanInfo.getPropertyDescriptors();
    }

    public static void setProperty(Object target, PropertyDescriptor prop, Object value) {
        try {
            Method setter = prop.getWriteMethod();
            if (setter == null) {
                return;
            }
            Class<?>[] params = setter.getParameterTypes();
            setter.invoke(target, TypeConvert.convert(params[0], value));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
